﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CarbonExchange.AmeeQuery;
using CarbonExchange.Dal;

namespace CarbonExchange.Bll
{
    public class SectionFactory : FactorySequenceBase<Section>
    {
        public SectionFactory() : base() { }
        public SectionFactory(IAmeeCommand command) : base(command) { }
        public SectionFactory(Context context) : base(context) { }
        public SectionFactory(IAmeeCommand command, Context context) : base(command, context) { }

        private IQueryable<Dal.Section> GetSelection()
        {
            return base.DalContext.Sections.Where(x => !x.Deleted).OrderBy(x => x.Sequence);
        }

        public Section GetById(int id)
        {
            return GetSelection().Where(x => x.Id == id).SingleOrDefault().Convert();
        }

        public IQueryable<Section> GetAll()
        {
            return GetSelection().Convert();
        }

        protected override object GetDataItemForUpdate(Section item)
        {
            return item.Convert(DalContext);
        }

        protected override void PopulateDataChanges(Section item, object dataItem)
        {
            var tmp = dataItem as Dal.Section;
            if (item.Id == 0)
            {
                item.Id = tmp.Id;
                item.Created = tmp.Created.ToLocalTime();
                item.Sequence = tmp.Sequence;
            }
        }

        protected override void MarkItemForDeletion(Section item)
        {
            if (item.Id > 0)
            {
                var dataItem = item.Convert(DalContext);
                dataItem.Deleted = true;
            }
        }

        protected override void SetDalSequence(Section item, int sequence)
        {
            var tmp = DalContext.Sections.Where(x => x.Id == item.Id && x.Sequence != sequence).SingleOrDefault();
            if (tmp != null)
            {
                tmp.Sequence = sequence;
            }
        }



        protected override void Validate(IQueryable<Section> items, CarbonExchange.Bll.Exceptions.ValidationException exp)
        {
            items.Validate(exp, DalContext);
        }

        protected override void SetInitalSequence(IQueryable<Section> items)
        {
            var tmpItems = items.Where(x => x.Id == 0).ToList();
            if (tmpItems.Count() > 1)
            {
                foreach (var item in tmpItems)
                {
                    item.Sequence = tmpItems.IndexOf(item);
                }
            }
        }
    }


    internal static class SectionFactoryConverter
    {
        internal static IQueryable<Section> Convert(this IQueryable<Dal.Section> source)
        {
            return source.Select(x => ConvertItem(x));
        }

        internal static Section Convert(this Dal.Section source)
        {
            return ConvertItem(source);
        }

        internal static Section ConvertItem(Dal.Section item)
        {
            if (item != null)
            {
                return new Section()
                {
                    Id = item.Id,
                    Name = item.Name,
                    Created = DateTime.SpecifyKind(item.Created, DateTimeKind.Utc).ToLocalTime(),
                    Sequence = item.Sequence
                };
            }
            else
            {
                return null;
            }
        }

        internal static Dal.Section Convert(this Section item, Dal.Context context)
        {
            Dal.Section dataItem = null;
            if (item.Id > 0)
            {
                dataItem = context.Sections.Where(i => i.Id == item.Id).Single();
            }
            else
            {
                dataItem = new CarbonExchange.Dal.Section();
                context.Sections.InsertOnSubmit(dataItem);
                dataItem.Created = DateTime.Now.ToUniversalTime();
                int? tmpMax = context.Sections.Where(x => !x.Deleted).Select(x => (int?)x.Sequence).Max();
                dataItem.Sequence = dataItem.Sequence + (tmpMax.HasValue ? tmpMax.Value + 1 : 0);
            }

            dataItem.Name = item.Name;

            return dataItem;
        }


        internal static void Validate(this IQueryable<Section> source, CarbonExchange.Bll.Exceptions.ValidationException e, Dal.Context context)
        {
            foreach(Section item in source)
            {
                item.Validate(e, context);
            }
        }

        internal static void Validate(this Section source, CarbonExchange.Bll.Exceptions.ValidationException e, Dal.Context context)
        {
            if (string.IsNullOrEmpty(source.Name))
            {
                e.Add("Section Name must be specified");
            }
        }
    }
}
